import socket
import threading
import time
from pprint import pprint

import gevent

from gevent import monkey
monkey.patch_all()


class TCPServer:

    def __init__(self, server_address, handler_class=None):
        self.server_address = server_address
        self.HandlerClass = handler_class  # 处理请求的类
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.is_shutdown = False
        self.con_list = []

    # 服务器的启动函数
    def server_forever(self):
        self.socket.bind(self.server_address)  # 绑定服务器地址
        self.socket.listen(1000)  # 启动并监听

        while not self.is_shutdown:
            # 1.接收请求
            sock_client, client_address = self.get_request()
            self.con_list.append(sock_client)
            pprint(self.con_list)
            print(len(self.con_list))
            # 2.处理请求
            try:
                # self.process_request(sock_client, client_address)
                self.process_req_by_thread(sock_client, client_address)
                # self.process_req_by_gevent(sock_client, client_address)
            except Exception as e:
                print(e)

    # 接受请求
    def get_request(self):
        return self.socket.accept()

    # 处理请求
    def process_request(self, sock_client, client_address):
        # 此处可定制请求处理业务
        try:

            print("received connection from {}".format(client_address))
            data = sock_client.recv(1024)
            print("data: {} from {}".format(data, client_address))
            time.sleep(1)
            sock_client.send(b"respect!!!")
        except Exception as e:
            print("client " + str(client_address) + " has disconnected")
            print(e)

        # 关闭连接
        self.close_request(sock_client)

    # 通过多线程处理请求
    def process_req_by_thread(self, request, client_address):
        t = threading.Thread(target=self.process_request, args=(request, client_address))
        t.start()
        t.join()

    # 通过协程处理请求
    def process_req_by_gevent(self, sock_client, client_address):
        g = gevent.spawn(self.process_request, sock_client, client_address)  # 生成一个协程让该connection对象去处理连接的业务
        # g.start()
        # g.join()

    # 关闭请求
    def close_request(self, sock_client):
        sock_client.shutdown(socket.SHUT_WR)
        sock_client.close()
        self.con_list.remove(sock_client)

    # 关闭服务器
    def shutdown(self):
        self.is_shutdown = True
